package com.gitee.wsl.android.ext

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import com.gitee.wsl.android.ext.ApplicationInit.application
import com.gitee.wsl.android.ext.PendingIntentExt.defaultUpdateFlags
import timber.log.Timber
import androidx.work.NetworkType
import androidx.work.WorkInfo

/**
 * detail: AlarmManager ( 全局定时器、闹钟 ) 工具类
 * @author Ttt
 * <pre>
 *     指定时长或以周期形式执行某项操作
 *     @see <a href="https://www.cnblogs.com/zyw-205520/p/4040923.html"/>
 *     关于使用 AlarmManager 的注意事项
 *     @see <a href="https://www.jianshu.com/p/d69a90bc44c0"/>
 * </pre>
 */
object AlarmExt {

    // ==========
    // = 开启闹钟 =
    // ==========
    /**
     * 开启一次性闹钟
     * @param triggerAtMillis 执行时间
     * @param pendingIntent   [PendingIntent] 响应动作
     * @return `true` success, `false` fail
     */
    
    fun startAlarmIntent(
        triggerAtMillis: Long,
        pendingIntent: PendingIntent
    ): Boolean {
        return startAlarmIntent(AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent)
    }

    /**
     * 开启一次性闹钟
     * @param type            闹钟类型, 常用的有 5 个值:
     * AlarmManager.ELAPSED_REALTIME、
     * AlarmManager.ELAPSED_REALTIME_WAKEUP、
     * AlarmManager.RTC、
     * AlarmManager.RTC_WAKEUP、
     * AlarmManager.POWER_OFF_WAKEUP
     * @param triggerAtMillis 执行时间
     * @param pendingIntent   [PendingIntent] 响应动作
     * @return `true` success, `false` fail
     */
    fun startAlarmIntent(
        type: Int,
        triggerAtMillis: Long,
        pendingIntent: PendingIntent
    ): Boolean {
        try {
            val manager: AlarmManager = application.alarmManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                manager.setExactAndAllowWhileIdle(type, triggerAtMillis, pendingIntent)
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                manager.setExact(type, triggerAtMillis, pendingIntent)
            } else {
                manager[type, triggerAtMillis] = pendingIntent
            }
            return true
        } catch (e: Exception) {
           Timber.d( e, "startAlarmIntent")
        }
        return false
    }

    // ==========
    // = 关闭闹钟 =
    // ==========
    /**
     * 关闭闹钟
     * @param pendingIntent [PendingIntent] 响应动作
     * @return `true` success, `false` fail
     */
    
    fun stopAlarmIntent(pendingIntent: PendingIntent): Boolean {
        try {
            application.alarmManager.cancel(pendingIntent)
            return true
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmIntent")
        }
        return false
    }
    
    // ===============
    // = Service 闹钟 =
    // ===============
    /**
     * 开启 Service 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param clazz           Class
     * @param action          Intent Action
     * @return `true` success, `false` fail
     */
    fun startAlarmService(
        context: Context,
        triggerAtMillis: Long,
        clazz: Class<*>,
        action: String
    ): Boolean {
        try {
            val intent = Intent(context, clazz)
            intent.action = action
            return startAlarmService(context, triggerAtMillis, intent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmService")
        }
        return false
    }

    /**
     * 开启 Service 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param intent          [ ][Intent]
     */
    
    fun startAlarmService(
        context: Context,
        triggerAtMillis: Long,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getService(
                context, 0, intent,
                defaultUpdateFlags
            )
            return startAlarmIntent(triggerAtMillis, pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmService")
        }
        return false
    }

    /**
     * 关闭 Service 闹钟
     * @param context [Context]
     * @param clazz   Class
     * @param action  Intent Action
     * @return `true` success, `false` fail
     */
    fun stopAlarmService(
        context: Context,
        clazz: Class<*>,
        action: String
    ): Boolean {
        try {
            val intent = Intent(context, clazz)
            intent.action = action
            return stopAlarmService(context, intent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmService")
        }
        return false
    }

    /**
     * 关闭 Service 闹钟
     * @param context [Context]
     * @param intent  [Intent]
     * @return `true` success, `false` fail
     */
    fun stopAlarmService(
        context: Context,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getService(
                context, 0, intent,
                defaultUpdateFlags
            )
            return stopAlarmIntent(pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmService")
        }
        return false
    }

    // =====================
    // = ForegroundService =
    // =====================
    /**
     * 开启 ForegroundService 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param clazz           Class
     * @param action          Intent Action
     * @return `true` success, `false` fail
     */
    fun startAlarmForegroundService(
        context: Context,
        triggerAtMillis: Long,
        clazz: Class<*>,
        action: String
    ): Boolean {
        try {
            val intent = Intent(context, clazz)
            intent.action = action
            return startAlarmForegroundService(context, triggerAtMillis, intent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmForegroundService")
        }
        return false
    }

    /**
     * 开启 ForegroundService 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param intent          [Intent]
     * @return `true` success, `false` fail
     */
    fun startAlarmForegroundService(
        context: Context,
        triggerAtMillis: Long,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getForegroundService(
                context, 0, intent,
                defaultUpdateFlags
            )
            return startAlarmIntent(triggerAtMillis, pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmForegroundService")
        }
        return false
    }

    /**
     * 关闭 ForegroundService 闹钟
     * @param context [Context]
     * @param clazz   Class
     * @param action  Intent Action
     * @return `true` success, `false` fail
     */
    fun stopAlarmForegroundService(
        context: Context,
        clazz: Class<*>,
        action: String
    ): Boolean {
        try {
            val intent = Intent(context, clazz)
            intent.action = action
            return stopAlarmForegroundService(context, intent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmForegroundService")
        }
        return false
    }

    /**
     * 关闭 ForegroundService 闹钟
     * @param context [Context]
     * @param intent  [Intent]
     * @return `true` success, `false` fail
     */
    fun stopAlarmForegroundService(
        context: Context,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getForegroundService(
                context, 0, intent,
                defaultUpdateFlags
            )
            return stopAlarmIntent(pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmForegroundService")
        }
        return false
    }
    

    // ==========================
    // = Broadcast Receiver 闹钟 =
    // ==========================
    /**
     * 开启 Receiver 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param intent          [Intent]
     * @return `true` success, `false` fail
     */
    fun startAlarmBroadcast(
        context: Context,
        triggerAtMillis: Long,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getBroadcast(
                context, 0, intent,
                defaultUpdateFlags
            )
            return startAlarmIntent(triggerAtMillis, pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmBroadcast")
        }
        return false
    }

    /**
     * 关闭 Receiver 闹钟
     * @param context [Context]
     * @param intent  [Intent]
     * @return `true` success, `false` fail
     */
    fun stopAlarmBroadcast(
        context: Context,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getBroadcast(
                context, 0, intent,
                defaultUpdateFlags
            )
            return stopAlarmIntent(pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmBroadcast")
        }
        return false
    }

    // ================
    // = Activity 闹钟 =
    // ================
    /**
     * 开启 Activity 闹钟
     * @param context         [Context]
     * @param triggerAtMillis 执行时间
     * @param intent          [Intent]
     * @return `true` success, `false` fail
     */
    fun startAlarmActivity(
        context: Context,
        triggerAtMillis: Long,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getActivity(
                context, 0, intent,
                defaultUpdateFlags
            )
            return startAlarmIntent(triggerAtMillis, pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "startAlarmActivity")
        }
        return false
    }

    /**
     * 关闭 Activity 闹钟
     * @param context [Context]
     * @param intent  [Intent]
     * @return `true` success, `false` fail
     */
    fun stopAlarmActivity(
        context: Context,
        intent: Intent
    ): Boolean {
        try {
            val pendingIntent = PendingIntent.getActivity(
                context, 0, intent,
                defaultUpdateFlags
            )
            return stopAlarmIntent(pendingIntent)
        } catch (e: Exception) {
           Timber.d( e, "stopAlarmActivity")
        }
        return false
    }
}

val Context.alarmManager :AlarmManager
    get() = getSystemService(Context.ALARM_SERVICE) as AlarmManager